<?php

class Profiler
{

	/**
	 * @var  array  collected benchmarks
	 */
	protected static $_marks = array();

	/**
	 * Starts a new benchmark and returns a unique token. The returned token
	 * _must_ be used when stopping the benchmark.
	 *
	 *     $token = Profiler::start('test', 'profiler');
	 *
	 * @param   string  $group group name
	 * @param   string  $info  profiler information
	 * @return  string
	 */
	public static function start($group, $info = null)
	{
		static $counter = 0;

		// Create a unique token based on the counter
		$token = 'pf/' . base_convert($counter++, 10, 32);

		Profiler::$_marks[$token] = array(
			'group' => strtolower($group),
			'info' => (string)$info,

			// Start the benchmark
			'start_time' => microtime(TRUE),
			'start_memory' => memory_get_usage(),

			// Set the stop keys without values
			'stop_time' => FALSE,
			'stop_memory' => FALSE,
			
			// ended
			'time'=> 0.0,
			'memory'=>0.0,
		);

		return $token;
	}

	/**
	 * Stops a benchmark.
	 *
	 *     Profiler::stop($token);
	 *
	 * @param   string  token
	 * @return  void
	 */
	public static function stop($token)
	{
		if (isset(Profiler::$_marks[$token]))
		{
			$mark = Profiler::$_marks[$token];
			$mark['stop_time'] = microtime(TRUE);
			$mark['stop_memory'] = memory_get_usage();
			$mark['time'] = $mark['stop_time']- $mark['start_time'];
			$mark['memory'] = $mark['stop_memory']- $mark['start_memory'];
			Profiler::$_marks[$token] = $mark;
		}
		
	}

	/**
	 * Deletes a benchmark. If an error occurs during the benchmark, it is
	 * recommended to delete the benchmark to prevent statistics from being
	 * adversely affected.
	 *
	 *     Profiler::delete($token);
	 *
	 * @param   string  token
	 * @return  void
	 */
	public static function delete($token)
	{
		// Remove the benchmark
		unset(Profiler::$_marks[$token]);
	}

	static public function stats()
	{
		$result = array();
		$groups = array();

		foreach (Profiler::$_marks as $token => $mark)
		{
			// Sort the tokens by the group and name
			$groups[$mark['group']][] = $mark;
		}

		foreach ($groups as $group => $marks)
		{
			$count = 0;
			$time = 0;
			$memory = 0;
			foreach ($marks as $mark)
			{
				$time += $mark['time'];
				$memory += $mark['memory'];
				$count++;
			}
			$result[$group] = array(
				'time' => $time,
				'memory' => $memory,
				'count' => $count
			);
		}

		unset($groups);
		return $result;
	}

	public static function detail()
	{
		return self::$_marks;
	}

} // End Profiler
